package cn.longwi.lwse.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.json.JSONUtil;
import cn.longwi.lwse.domain.LicenseInfo;
import cn.longwi.lwse.domain.RespResult;
import cn.longwi.lwse.domain.ResponseCode;
import cn.longwi.lwse.properties.LicenseProperties;
import cn.longwi.lwse.utils.HardwareInfoUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

@Service
public class LicenseService {

    @Resource
    private LicenseProperties licenseProperties;

    private final String LOG_NAME = "lwse.log";

    /**
     * 授权码是否有效
     * @return RespResult
     */
    public RespResult hasValidLicense() {
        return hasValidLicense(null);
    }
    /**
     * 授权码是否有效
     * @param license 授权码
     * @return RespResult
     */
    public RespResult hasValidLicense(String license) {
        RespResult respResult;
        if (StrUtil.isBlank(license)) {
            respResult = parseLicenseKey();
        }else {
            respResult = parseLicenseKey(license);
        }
        if (respResult.getCode() != ResponseCode.SUCCESS.getCode()) {
             return respResult;
        }
        try {
            LicenseInfo licenseInfo = (LicenseInfo)respResult.getData();
            LocalDate nowDate = LocalDate.now();
            LocalDate endDate = licenseInfo.getEndDate();
            String hardwareIdentifier = HardwareInfoUtil.getHardwareIdentifier();
            if (!hardwareIdentifier.equals(licenseInfo.getHardwareIdentifier())){
                return RespResult.error(ResponseCode.LICENSE_INVALID,null);
            }
            long daysBetween = ChronoUnit.DAYS.between(nowDate, endDate);
            if (daysBetween < 0){
                return RespResult.error(ResponseCode.LICENSE_EXPIRE,null);
            }
            String licensePath = licenseProperties.getLicensePath();
            String separator = File.separator;
            if (!licensePath.endsWith(separator)){
                licensePath = licensePath + separator;
            }
            String logFile = licensePath + LOG_NAME;
            FileUtil.writeString(LocalDate.now().toString(),logFile,StandardCharsets.UTF_8);
            return RespResult.success(licenseInfo);
        }catch (Exception e){
            return RespResult.error(ResponseCode.LICENSE_INVALID,null);
        }
    }

    public boolean isValidateCurrentDay(){
        String licensePath = licenseProperties.getLicensePath();
        String separator = File.separator;
        if (!licensePath.endsWith(separator)){
            licensePath = licensePath + separator;
        }
        String logFile = licensePath + LOG_NAME;
        if (!new File(logFile).exists()){
            return false;
        }
        String nowStr = LocalDate.now().toString();
        String readDate = FileUtil.readString(logFile, StandardCharsets.UTF_8);
        return nowStr.equals(readDate);
    }

    /**
     * 注册授权码
     * @param license 授权码
     * @return RespResult
     */
    public RespResult registerLicense(String license) {
        if (StrUtil.isEmpty(license)) {
             return RespResult.error(ResponseCode.LICENSE_INVALID,null);
        }
        RespResult respResult = hasValidLicense(license);
        if (respResult.getCode() != ResponseCode.SUCCESS.getCode()){
             return respResult;
        }
        //获取授权目录
        RespResult licenseFileRes = getLicenseFilePath();
        if (licenseFileRes.getCode() != ResponseCode.SUCCESS.getCode()){
            return licenseFileRes;
        }
        String filePath = licenseFileRes.getData().toString();
        FileUtil.writeString(license,filePath, StandardCharsets.UTF_8);
        return RespResult.success(null);
    }

    /**
     * 授权码解析
     * @param licenseKey 授权码
     * @return RespResult
     */
    public RespResult parseLicenseKey(String licenseKey){
        if (StrUtil.isBlank(licenseKey)) {
            RespResult respResult = getLicenseKey();
            if (respResult.getCode() != ResponseCode.SUCCESS.getCode()){
                return respResult;
            }
            licenseKey = respResult.getData().toString();
        }
        String publicKey = getRsaKey("public");
        if (StrUtil.isBlank(publicKey)){
            return RespResult.error(ResponseCode.LICENSE_INVALID_KEY,null);
        }
        try {
            SecureUtil.disableBouncyCastle();
            RSA rsa = new RSA(null,publicKey);
            String decryptLicense = rsa.decryptStr(licenseKey, KeyType.PublicKey);
            LicenseInfo licenseInfo = JSONUtil.toBean(decryptLicense, LicenseInfo.class);
            if (licenseInfo == null || StrUtil.hasBlank(licenseInfo.getCompanyName(),licenseInfo.getHardwareIdentifier())
                    || licenseInfo.getEndDate() == null){
                return RespResult.error(ResponseCode.LICENSE_INVALID,null);
            }
            return RespResult.success(licenseInfo);
        }catch (Exception e){
           return RespResult.error(ResponseCode.LICENSE_INVALID,e.getMessage());
        }
    }

    /**
     * 授权码解析
     * @return RespResult
     */
    public RespResult parseLicenseKey(){
        return parseLicenseKey(null);
    }

    /**
     * 获取授权码
     * @return RespResult
     */
    public RespResult getLicenseKey(){
        RespResult licenseFileRes = getLicenseFilePath();
        if (licenseFileRes.getCode() != ResponseCode.SUCCESS.getCode()){
            return licenseFileRes;
        }
        String filePath = licenseFileRes.getData().toString();
        try {
            String licenseKey = FileUtil.readString(filePath, StandardCharsets.UTF_8);
            return RespResult.success(licenseKey);
        }catch (IORuntimeException e){
            return RespResult.error(ResponseCode.LICENSE_INVALID,null);
        }
    }

    /**
     * 获取授权目录
     * @return RespResult
     */
    public RespResult getLicenseFilePath(){
        String licensePath = licenseProperties.getLicensePath();
        if (StrUtil.isBlank(licensePath) || !new File(licensePath).isDirectory()){
            return RespResult.error(ResponseCode.DIR_EMPTY,null);
        }
        if (StrUtil.isBlank(licensePath) || !new File(licensePath).isDirectory()){
            String msg = licensePath + ResponseCode.DIR_NOT_EXITS.getMsg();
            return new RespResult(ResponseCode.DIR_NOT_EXITS.getCode(),msg,null);
        }
        String separator = File.separator;
        if (!licensePath.endsWith(separator)){
            licensePath = licensePath + separator;
        }
        String licenseFileName = "license.pem";
        String filePath =licensePath + licenseFileName;
        return RespResult.success(filePath);
    }



    /**
     * 获取RSA key
     * @param type private 或者 public
     * @return RSA key
     */
    public String getRsaKey(String type) {
        if (StrUtil.isBlank(type)){
            return null;
        }
        String keyPath = null;
        if (type.equals("private")){
            keyPath = "lwkey/license_private_key.pem";
        }else if (type.equals("public")){
            keyPath = "lwkey/license_public_key.pem";
        }
        if (StrUtil.isBlank(keyPath)){
            return null;
        }
        String rsaKey = ResourceUtil.readUtf8Str(keyPath);
        rsaKey = rsaKey.replaceAll("-----BEGIN (.*)-----", "")
                .replaceAll("-----END (.*)-----", "")
                .replaceAll("\\s+", ""); // 去除空白符
        return rsaKey;
    }
}
